#include"Graph.h"
#include <queue>
#include <map>
extern TerminalSymbol dollar;

DFA::DFA(NonTerminalSymbol *start_symbol){
    assert(start_symbol->production_table.size()==1);//开始节点等于一
    this->startup_item_set=make_shared<DFANode>(0,LR0Item(start_symbol,start_symbol->production_table.front(),0));
    this->items_map[this->startup_item_set.get()->item_table]=0;
    nodes.push_back(startup_item_set);
    build_DFA();
};

void DFA::build_DFA(){
    //初始化DFA节点之后，调用的方法
    queue<int> que;
    que.push(0);
    set<int> inited_state;
    while(!que.empty()){
        int from_state_id=que.front();
        que.pop();
        if(inited_state.count(from_state_id)){
            continue; //已经遍历过的不用遍历了
        }
        auto &item_table=this->nodes[from_state_id].get()->item_table;
        auto &transition=nodes[from_state_id].get()->transition;
        map<GrammarSymbol*,DFANode> mp;
        for(auto item_ptr:item_table){
            
            GrammarSymbol*g_symbol=item_ptr.get_excepted_symbol();
            if(g_symbol)
                mp[g_symbol].add_item(LR0Item(item_ptr.non_terminal_symbol,item_ptr.production_id,item_ptr.dot_position+1,CORE));
            
        }

        for(auto &elem:mp){
            int to_state_id;
            if(this->items_map.count(elem.second.item_table)){
                //原有状态
                to_state_id=this->items_map[elem.second.item_table];
            }else{
                //新状态
                shared_ptr<DFANode> new_node=make_shared<DFANode>(elem.second);
                this->items_map[elem.second.item_table]=this->nodes.size();
                new_node.get()->state_id=this->nodes.size();
                to_state_id=this->nodes.size();
                this->nodes.push_back(new_node);
                que.push(to_state_id);
            }
            this->nodes[from_state_id].get()->transition[elem.first]=to_state_id;
            
        }
        //this->nodes[from_state_id].get()->get_info();
        inited_state.insert(from_state_id);
        
    }
};

bool DFA::calcu_action(vector<TerminalSymbol*> &grammar_symbol_vct){
    cout<<"\t";
    for(auto &elem:grammar_symbol_vct){
        cout<<elem->get_name()<<"\t";
    }cout<<endl;
    for(auto &node: nodes){
        cout<<node.get()->state_id<<"\t";
        for(auto &terminal:grammar_symbol_vct){
            if(node.get()->reduce_mp.count(terminal) && node.get()->transition.count(terminal)){
                //shift 和reduce冲突
                cout<<"shift / reduce conflict"<<endl;
                return false;
            }
            if(node.get()->reduce_mp.count(terminal)){
                cout<<"r"<<node.get()->reduce_mp[terminal]<<"\t";
            }
            else if(node.get()->transition.count(terminal)){
                cout<<"s"<<node.get()->transition[terminal]<<"\t";
            }else{
                cout<<"\t";
            }

        }
        cout<<endl;
    }
};

void DFA::calcu_goto(vector<NonTerminalSymbol*> &grammar_symbol_vct){
    cout<<"\t";
    for(auto &elem:grammar_symbol_vct){
        cout<<elem->get_name()<<"\t";
    }cout<<endl;
    for(auto &node: nodes){
        cout<<node.get()->state_id<<"\t";
        for(auto &terminal:grammar_symbol_vct){
            if(node.get()->transition.count(terminal)){
                cout<<"s"<<node.get()->transition[terminal]<<"\t";
            }else{
                cout<<"\t";
            }

        }
        cout<<endl;
    }
};